﻿/*****************************************介绍*****************************************
 * 作者：User
 * 创建时间：2025-09-26 11:53:49
 * 功能：地图拖拽
**************************************************************************************/

using System.Collections;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;

namespace Game.UI.HallPanel
{
    [RequireComponent(typeof(Image))]
    public class DraggableMap : MonoBehaviour, IDragHandler, IBeginDragHandler, IEndDragHandler
    {
        [Header("地图设置")]
        [SerializeField] private RectTransform mapRectTransform;
        [SerializeField] private RectTransform canvasRectTransform;

        [Header("拖拽设置")]
        [SerializeField] private bool enableDrag = true;
        [SerializeField] private float dragSensitivity = 1.0f;

        [Header("惯性效果设置")]
        [SerializeField] private bool enableInertia = true;
        [SerializeField] private float inertiaDeceleration = 0.95f; // 惯性减速度
        [SerializeField] private float minVelocityToStop = 5f;      // 停止的最小速度
        [SerializeField] private float maxVelocity = 1000f;         // 最大速度限制

        private Vector2 mapSize;
        private Vector2 canvasSize;
        private Vector2 minPosition;
        private Vector2 maxPosition;
        private Vector3 originalPosition;
        private bool isInitialized = false;

        // 惯性效果相关变量
        private Vector2 currentVelocity;
        private bool isInertiaMoving = false;
        private Vector2[] dragVelocities = new Vector2[5]; // 存储最近5帧的速度
        private int velocityIndex = 0;

        // 目标移动相关变量
        private Vector3 targetPosition;
        private bool isMovingToTarget = false;
        private float moveSpeed = 5f;

        private void Awake()
        {
            Initialize();
        }

        private void Initialize()
        {
            if (isInitialized) return;

            if (mapRectTransform == null)
                mapRectTransform = GetComponent<RectTransform>();

            if (canvasRectTransform == null)
                canvasRectTransform = GetComponentInParent<Canvas>().GetComponent<RectTransform>();

            // 获取地图和画布尺寸
            mapSize = mapRectTransform.rect.size;
            canvasSize = canvasRectTransform.rect.size;

            // 计算边界限制
            CalculateBounds();

            // 保存原始位置
            originalPosition = mapRectTransform.localPosition;

            // 初始化速度数组
            for (int i = 0; i < dragVelocities.Length; i++)
            {
                dragVelocities[i] = Vector2.zero;
            }

            isInitialized = true;
        }

        private void CalculateBounds()
        {
            float maxX = Mathf.Max(0, (mapSize.x - canvasSize.x) * 0.5f);
            float maxY = Mathf.Max(0, (mapSize.y - canvasSize.y) * 0.5f);

            minPosition = new Vector2(-maxX, -maxY);
            maxPosition = new Vector2(maxX, maxY);
        }

        public void OnBeginDrag(PointerEventData eventData)
        {
            if (!enableDrag) return;

            // 停止所有移动效果
            isMovingToTarget = false;
            isInertiaMoving = false;
            currentVelocity = Vector2.zero;

            // 重置速度记录
            for (int i = 0; i < dragVelocities.Length; i++)
            {
                dragVelocities[i] = Vector2.zero;
            }
        }

        public void OnDrag(PointerEventData eventData)
        {
            if (!enableDrag || !isInitialized) return;

            // 停止惯性移动
            isInertiaMoving = false;

            // 计算拖拽位移
            Vector2 delta = eventData.delta * dragSensitivity;

            // 记录当前帧的速度（基于时间缩放）
            Vector2 frameVelocity = delta / Time.deltaTime;
            RecordVelocity(frameVelocity);

            // 应用位移
            Vector3 newPosition = mapRectTransform.localPosition + new Vector3(delta.x, delta.y, 0);

            // 限制在边界内
            newPosition = ClampPosition(newPosition);

            mapRectTransform.localPosition = newPosition;
        }

        public void OnEndDrag(PointerEventData eventData)
        {
            if (!enableDrag || !enableInertia) return;

            // 计算平均速度
            Vector2 averageVelocity = CalculateAverageVelocity();

            // 如果速度足够大，开始惯性移动
            if (averageVelocity.magnitude > minVelocityToStop)
            {
                currentVelocity = Vector2.ClampMagnitude(averageVelocity, maxVelocity);
                isInertiaMoving = true;
                StartCoroutine(InertiaMove());
            }
        }

        /// <summary>
        /// 记录当前帧的速度
        /// </summary>
        private void RecordVelocity(Vector2 velocity)
        {
            dragVelocities[velocityIndex] = velocity;
            velocityIndex = (velocityIndex + 1) % dragVelocities.Length;
        }

        /// <summary>
        /// 计算平均速度
        /// </summary>
        private Vector2 CalculateAverageVelocity()
        {
            Vector2 sum = Vector2.zero;
            int count = 0;

            for (int i = 0; i < dragVelocities.Length; i++)
            {
                if (dragVelocities[i] != Vector2.zero)
                {
                    sum += dragVelocities[i];
                    count++;
                }
            }

            return count > 0 ? sum / count : Vector2.zero;
        }

        /// <summary>
        /// 惯性移动协程
        /// </summary>
        private IEnumerator InertiaMove()
        {
            while (isInertiaMoving && currentVelocity.magnitude > minVelocityToStop)
            {
                // 应用惯性移动
                Vector3 delta = currentVelocity * Time.deltaTime;
                Vector3 newPosition = mapRectTransform.localPosition + new Vector3(delta.x, delta.y, 0);

                // 限制在边界内
                newPosition = ClampPosition(newPosition);

                // 检查是否碰到边界
                bool hitBoundaryX = Mathf.Approximately(newPosition.x, minPosition.x) ||
                                   Mathf.Approximately(newPosition.x, maxPosition.x);
                bool hitBoundaryY = Mathf.Approximately(newPosition.y, minPosition.y) ||
                                   Mathf.Approximately(newPosition.y, maxPosition.y);

                // 如果碰到边界，反弹并减小速度
                if (hitBoundaryX) currentVelocity.x *= -0.3f;
                if (hitBoundaryY) currentVelocity.y *= -0.3f;

                mapRectTransform.localPosition = newPosition;

                // 减小速度（惯性衰减）
                currentVelocity *= inertiaDeceleration;

                // 如果速度很小，停止惯性
                if (currentVelocity.magnitude <= minVelocityToStop)
                {
                    isInertiaMoving = false;
                }

                yield return null;
            }

            isInertiaMoving = false;
            currentVelocity = Vector2.zero;
        }

        /// <summary>
        /// 限制位置在边界内
        /// </summary>
        private Vector3 ClampPosition(Vector3 position)
        {
            position.x = Mathf.Clamp(position.x, minPosition.x, maxPosition.x);
            position.y = Mathf.Clamp(position.y, minPosition.y, maxPosition.y);
            return position;
        }

        /// <summary>
        /// 将指定地点移动到Canvas中心（使用UI坐标，即RectTransform.anchoredPosition）
        /// </summary>
        public void FocusOnLocationLocal(Vector2 targetLocalPosition)
        {
            if (!isInitialized) Initialize();

            // 停止惯性移动
            isInertiaMoving = false;
            StopAllCoroutines();

            Vector3 offset = -targetLocalPosition;
            Vector3 newPosition = offset;
            newPosition = ClampPosition(newPosition);

            if (Application.isPlaying)
            {
                targetPosition = newPosition;
                isMovingToTarget = true;
            }
            else
            {
                mapRectTransform.localPosition = newPosition;
            }
        }

        /// <summary>
        /// 重置地图位置到中心
        /// </summary>
        public void ResetPosition()
        {
            if (!isInitialized) Initialize();

            // 停止惯性移动
            isInertiaMoving = false;
            StopAllCoroutines();

            if (Application.isPlaying)
            {
                targetPosition = originalPosition;
                isMovingToTarget = true;
            }
            else
            {
                mapRectTransform.localPosition = originalPosition;
            }
        }

        private void Update()
        {
            // 平滑移动到目标位置
            if (isMovingToTarget && !isInertiaMoving)
            {
                mapRectTransform.localPosition = Vector3.Lerp(
                    mapRectTransform.localPosition,
                    targetPosition,
                    moveSpeed * Time.deltaTime
                );

                if (Vector3.Distance(mapRectTransform.localPosition, targetPosition) < 0.1f)
                {
                    mapRectTransform.localPosition = targetPosition;
                    isMovingToTarget = false;
                }
            }
        }

        /// <summary>
        /// 启用/禁用拖拽功能
        /// </summary>
        public void SetDragEnabled(bool enabled)
        {
            enableDrag = enabled;
            if (!enabled)
            {
                // 禁用时停止所有移动
                isInertiaMoving = false;
                isMovingToTarget = false;
                StopAllCoroutines();
            }
        }

        /// <summary>
        /// 启用/禁用惯性效果
        /// </summary>
        public void SetInertiaEnabled(bool enabled)
        {
            enableInertia = enabled;
            if (!enabled)
            {
                isInertiaMoving = false;
                StopAllCoroutines();
            }
        }

        /// <summary>
        /// 设置拖拽灵敏度
        /// </summary>
        public void SetDragSensitivity(float sensitivity)
        {
            dragSensitivity = Mathf.Clamp(sensitivity, 0.1f, 5f);
        }

        /// <summary>
        /// 设置惯性参数
        /// </summary>
        public void SetInertiaParameters(float deceleration, float minStopVelocity, float maxVelocityLimit)
        {
            inertiaDeceleration = Mathf.Clamp01(deceleration);
            minVelocityToStop = Mathf.Max(0.1f, minStopVelocity);
            maxVelocity = Mathf.Max(10f, maxVelocityLimit);
        }

        /// <summary>
        /// 立即停止所有移动（包括惯性和平滑移动）
        /// </summary>
        public void StopAllMovement()
        {
            isInertiaMoving = false;
            isMovingToTarget = false;
            currentVelocity = Vector2.zero;
            StopAllCoroutines();
        }

        // 在Inspector中更改尺寸时重新计算边界
        private void OnValidate()
        {
            if (isInitialized)
            {
                CalculateBounds();
            }
        }

        // 当组件启用时自动初始化
        private void OnEnable()
        {
            Initialize();
        }

        // 当组件禁用时停止所有协程
        private void OnDisable()
        {
            StopAllCoroutines();
        }
    }
}